package org.openjsonp.json;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.json.JsonArray;
import javax.json.JsonNumber;
import javax.json.JsonObject;
import javax.json.JsonString;
import javax.json.JsonValue;

/**
 * Implementation of the interface {@link javax.json.JsonArray JsonArray}.
 * 
 */
public class JsonArrayImpl extends ArrayList<JsonValue> implements JsonArray {

	private static final long serialVersionUID = 7372668427189468340L;

	/**
	 * Default constructor.
	 * <p>
	 * Constructs an empty list with an initial capacity of ten.
	 * </p>
	 */
	public JsonArrayImpl() {
		super();
	}

	/**
	 * Constructs a list containing the elements of the specified collection, in
	 * the order they are returned by the collection's iterator.
	 * <p>
	 * If the collection is <i>null</i>, constructs with an empty list.
	 * </p>
	 * 
	 * @param c the collection whose elements are to be placed into this list
	 * 
	 */
	public JsonArrayImpl(Collection<? extends JsonValue> c) {
		super(c != null ? c : new ArrayList<JsonValue>());
	}

	/**
	 * Constructs an empty list with the specified initial capacity.
	 * <p>
	 * if the specified initial capacity is negative, then constructs an empty
	 * list with the default initial capacity (10).
	 * </p>
	 * 
	 * @param initialCapacity the initial capacity of the list
	 * 
	 */
	public JsonArrayImpl(int initialCapacity) {
		super(initialCapacity >= 0 ? initialCapacity : 10);
	}

	@Override
	public ValueType getValueType() {
		return ValueType.ARRAY;
	}

	@Override
	public JsonObject getJsonObject(int index) {
		return (JsonObject) get(index);
	}

	@Override
	public JsonArray getJsonArray(int index) {
		return (JsonArray) get(index);
	}

	@Override
	public JsonNumber getJsonNumber(int index) {
		return (JsonNumber) get(index);
	}

	@Override
	public JsonString getJsonString(int index) {
		return (JsonString) get(index);
	}

	@Override
	public <T extends JsonValue> List<T> getValuesAs(Class<T> clazz) {
		// Best approch ?
		List<T> list = new ArrayList<T>(size());
		list.addAll((Collection<T>) this);
		return list;
	}

	@Override
	public String getString(int index) {
		return getJsonString(index).getString();
	}

	@Override
	public String getString(int index, String defaultValue) {
		JsonValue jsonValue = get(index);
		String stringValue = defaultValue;

		if (JsonValue.ValueType.STRING.equals(jsonValue.getValueType())) {
			stringValue = ((JsonString) jsonValue).getString();
		}

		return stringValue;
	}

	@Override
	public int getInt(int index) {
		return getJsonNumber(index).intValue();
	}

	@Override
	public int getInt(int index, int defaultValue) {
		JsonValue value = get(index);
		int intValue = defaultValue;

		if (ValueType.NUMBER.equals(value.getValueType())) {
			intValue = ((JsonNumber) value).intValue();
		}

		return intValue;
	}

	@Override
	public boolean getBoolean(int index) {
		JsonValue value = get(index);
		boolean booleanValue;

		if (JsonValue.TRUE.equals(value)) {
			booleanValue = true;
		}
		else if (JsonValue.FALSE.equals(value)) {
			booleanValue = false;
		}
		else {
			throw new ClassCastException(
					"Expected class type javax.json.JsonValue.ValueType.TRUE or javax.json.JsonValue.ValueType.FALSE. Actual : "
							+ value.getClass());
		}

		return booleanValue;
	}

	@Override
	public boolean getBoolean(int index, boolean defaultValue) {
		JsonValue value = get(index);
		boolean booleanValue = defaultValue;

		if (JsonValue.TRUE.equals(value)) {
			booleanValue = true;
		}
		else if (JsonValue.FALSE.equals(value)) {
			booleanValue = false;
		}

		return booleanValue;
	}

	@Override
	public boolean isNull(int index) {
		JsonValue value = get(index);
		return JsonValue.NULL.equals(value);
	}

	@Override
	public String toString() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("[\n");
		for (JsonValue value : this) {
			buffer.append(value);
			buffer.append(",\n");
		}
		buffer.delete(buffer.length() - 2, buffer.length() - 1);
		buffer.append("]");
		return buffer.toString();
	}
}
